#include <cocos2d.h>
#include "CCIceSession.h"
#include "SessionHelper.h"
#include <iostream>
#include "IceLuaSupport.h"

USING_NS_CC;

///////////////////////////////////////////////////////////////////////
void LuaException::registerException(const std::string& exceptionName)
{
}

LuaException::LuaException(const std::string& name)
:stream(NULL)
{
    _exName = name;
}

LuaException::~LuaException() throw ()
{
    if (stream)
    {
        delete stream;
    }
}

std::string LuaException::ice_name() const
{
    return this->_exName;
}

LuaException* LuaException::ice_clone() const
{
    return new LuaException(*this);
}

void LuaException::ice_throw() const
{
    throw *this;
}

void LuaException::__writeImpl(::IceInternal::BasicStream * __os) const
{
    __os->startWriteSlice(_exName, -1, true);
    __os->endWriteSlice();
}

void LuaException::__readImpl(::IceInternal::BasicStream * __is)
{
    _is = __is;
}

InputStreamWrapper* LuaException::getStream()
{
    _is->startReadSlice();
    stream = new InputStreamWrapper(_is);
    return stream;
}



ConnectionInfo::ConnectionInfo(string ip, int port, string account, string password, int timeout, string routerName)
	:account(account)
	,password(password)
{
		properties = Ice::createProperties();

		std::stringstream buf;
		buf << routerName <<"/router:tcp" << " -p " << port << " -h " << ip << " -t " << timeout * 1000 << std::endl;

		properties->setProperty("Ice.ACM.Client", "0");
		properties->setProperty("Ice.ACM.Server", "0");
		properties->setProperty("Ice.RetryIntervals", "-1");
		properties->setProperty("Ice.Trace.Network", "1");
		properties->setProperty("Ice.Default.Router", buf.str());
		properties->setProperty("Ice.Trace.ThreadPool", "1");
}

ConnectionInfo::ConnectionInfo()
{
	properties = Ice::createProperties();

	properties->setProperty("Ice.ACM.Client", "0");
	properties->setProperty("Ice.ACM.Server", "0");
	properties->setProperty("Ice.RetryIntervals", "-1");
	properties->setProperty("Ice.Trace.Network", "1");
	properties->setProperty("Ice.Trace.ThreadPool", "1");
}

void ConnectionInfo::setProperty(const std::string& key, const std::string& value)
{
	properties->setProperty(key, value);
}

//////////////////////////////////////////////////////////////////////////


void CCIceSession::createdCommunicator(SessionHelper* session)
{
}

void CCIceSession::connected(SessionHelper* session){
    Glacier2::SessionPrx prx = session->session();
	eventConnected();
}

void CCIceSession::disconnected(SessionHelper* session) {
	eventDisconnected();
	Director::getInstance()->getScheduler()->unscheduleAllForTarget(this);
}

void CCIceSession::connectFailed(SessionHelper* session,const Ice::Exception& ex) {
	eventConnectFailed(&ex);
	Director::getInstance()->getScheduler()->unscheduleAllForTarget(this);
}

//////////////////////////////////////////////////////////////////////////

CCIceSession::CCIceSession()
{
}

CCIceSession::~CCIceSession()
{
}

CCIceSession* CCIceSession::create()
{
	CCIceSession* ccsession = new CCIceSession();
	if (ccsession) {
		if (!ccsession->init()) {
			delete ccsession;
			ccsession = NULL;
		}
	}

	return ccsession;
}

bool CCIceSession::init()
{
	return true;
}

void CCIceSession::update(float dt)
{
	_sessionHelper->update();
}

bool CCIceSession::connect (const ConnectionInfo& info) 
{
	Ice::InitializationData* initData = new Ice::InitializationData();
	initData->properties = info.properties;

	initData->dispatcher = new IceDispatcher(initData->logger);
	_sessionHelper = new SessionHelper(this, initData);
	_sessionHelper->connect(info.account,info.password);

    Director::getInstance()->getScheduler()->scheduleUpdate(this, 0, false);
	return true;
}

void CCIceSession::disconnect()
{
	std::cout<<"disconnect"<<std::endl;
	if(_sessionHelper){
		_sessionHelper->destroy();
	}
}

Ice::ObjectPrx CCIceSession::addCallback(const std::string& name, int luaCallback)
{
	return addServant(name, new CallbackI(luaCallback));	
}

Ice::ObjectPrx  CCIceSession::addCallbackFacet(const std::string& name, const std::string& facet, int luaCallback)
{
	Ice::ObjectAdapterPtr myAdapter = _sessionHelper->objectAdapter();
	Ice::Identity id = _sessionHelper->createCallbackIdentity(name);
	return myAdapter->addFacet(new CallbackI(luaCallback), id, facet);
}

Ice::ObjectPrx CCIceSession::addServant(const std::string& name, Ice::ObjectPtr servant)
{
	if(_sessionHelper!= NULL){
		Ice::Identity id = _sessionHelper->communicator()->stringToIdentity(name);
		return _sessionHelper->objectAdapter()->add(servant,id);
	}
	return NULL;
}

bool CCIceSession::invoke(const std::string& facet, const std::string& operation, std::vector<Ice::Byte>* params, int handler)
{
	Ice::ObjectPrx prx  = _sessionHelper->session()->ice_facet(facet);

	if(prx){
		AMI_Object_ice_invoke_lua* cb = new  AMI_Object_ice_invoke_lua(handler, prx);
		prx->begin_ice_invoke(operation,Ice::Normal,*params, (const ::Ice::Callback_Object_ice_invokePtr&)cb);
		return true;
	//	return prx->ice_invoke_async(new AMI_Object_ice_invoke_lua(handler,prx),operation,Ice::Normal,*params);
	}
	else{
	//	CCLOG("facet:%s not find!",facet.c_str());
		return false;
	}
}

Ice::OutputStream* CCIceSession::createOutputStream()
{
	return Ice::createOutputStream(_sessionHelper->session()->ice_getCommunicator()).get();
}
